package sunbt.gistools.util;

import org.locationtech.jts.geom.*;

/**
 * @author sunbt
 * @version 1.0
 * @date 2025/7/17 22:36
 * GeometryUtils工具类，用于处理几何对象。
 */
public class GeometryUtils {

    /**
     * 将带有Z值的Geometry转换为不带Z值的Geometry（删除Z坐标），如果几何对象没有Z值则不进行处理。
     *
     * @param geometry 含有或可能不含Z值的几何对象
     * @return 无Z值的二维几何对象（如果原始几何对象有Z值）
     */
    public static Geometry removeZIfExists(Geometry geometry) {
        if (geometry == null) {
            return null;
        }

        // 检查几何对象是否包含Z值
        boolean hasZ = false;
        for (Coordinate coord : geometry.getCoordinates()) {
            if (!Double.isNaN(coord.getZ())) {
                hasZ = true;
                break;
            }
        }

        // 如果没有Z值，直接返回原始几何对象
        if (!hasZ) {
            return geometry;
        }

        // 创建一个新的Geometry工厂，指定目标类型为无Z坐标的Geometry
        GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);

        // 使用CoordinateSequenceFilter移除Z坐标
        geometry.apply(new CoordinateSequenceFilter() {
            @Override
            public void filter(CoordinateSequence seq, int i) {
                // 将Z坐标设置为NaN
                seq.setOrdinate(i, 2, Double.NaN);
            }

            @Override
            public boolean isDone() {
                return false;
            }

            @Override
            public boolean isGeometryChanged() {
                return true;
            }
        });

        // 创建新的二维Geometry
        return geometryFactory.createGeometry(geometry);
    }


    /**
     * 递归地将几何对象中的坐标调整为 [经度, 纬度] 的顺序
     *
     * @param geometry 要调整坐标顺序的几何对象
     */
    private static void transformCoordinatesToLongLat(Geometry geometry) {
        if (geometry instanceof Point || geometry instanceof MultiPoint ||
                geometry instanceof LineString || geometry instanceof MultiLineString ||
                geometry instanceof Polygon || geometry instanceof MultiPolygon) {

            Coordinate[] coordinates = geometry.getCoordinates();
            for (Coordinate coord : coordinates) {
                // 如果纬度在前，经度在后，交换它们
                if (Math.abs(coord.x) < Math.abs(coord.y)) {
                    double temp = coord.x;
                    coord.x = coord.y;
                    coord.y = temp;
                }
            }
        } else if (geometry instanceof GeometryCollection) {
            // 递归处理GeometryCollection中的每个子几何体
            int numGeometries = geometry.getNumGeometries();
            for (int i = 0; i < numGeometries; i++) {
                transformCoordinatesToLongLat(geometry.getGeometryN(i));
            }
        }
    }

}
